package com.xrui.hbase.conversion;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.io.Serializable;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * This class is a base class for type converters.
 */
@SuppressWarnings("CallToSimpleGetterFromWithinClass")
public abstract class TypeConverter implements Comparable<TypeConverter>, Serializable {

    //region Constants
    protected final static Logger LOG = LoggerFactory.getLogger(TypeConverter.class);
    protected static final byte[] EMPTY_BYTES_ARRAY = new byte[0];

    private static final long serialVersionUID = 1490434164342371320L;
    //endregion

    //region Variables
    private String name;
    private String code;
    //endregion

    //region Constructor
    protected TypeConverter() {
        this.name = this.getClass().getSimpleName().replace("Converter", "");
    }
    //endregion

    //region Public Methods

    /**
     * Gets the code of the type converter if available.
     *
     * @return The original code.
     */
    public String getCode() {
        return code;
    }

    /**
     * Sets the code for the type converter.
     *
     * @param code The code to set.
     */
    public void setCode(String code) {
        this.code = code;
    }

    /**
     * Gets the name of the converter to be presented as a column type.
     *
     * @return The name of the converter.
     */
    public String getName() {
        return this.name;
    }

    /**
     * Checks whether the type converter can be edited.
     *
     * @return True if the type converter can be edited or False otherwise.
     */
    public boolean isEditable() {
        return code != null;
    }

    /**
     * Indicates whether the type converter can be used for column name conversions.
     *
     * @return True if the type converter can be used for column name conversions or False otherwise.
     */
    public boolean isValidForNameConversion() {
        return false;
    }

    /**
     * Converts an {@link String} to an array of bytes.
     *
     * @param value An string to convert.
     * @return A converted byte array.
     */
    public abstract byte[] toBytes(String value);

    /**
     * Converts an {@link byte[]} to a {@link String}.
     *
     * @param value An byte[] to convert.
     * @return A converted string.
     */
    public abstract String toString(byte[] value);

    /**
     * Checks whether the provided value can be converted to the type supported by this converter.
     *
     * @param value The value to check.
     * @return True if the value can be converted by the converter to the required type of False otherwise.
     */
    public abstract boolean canConvert(byte[] value);

    /**
     * Indicates whether the type converter supports formatting of the data.
     *
     * @return True if the type converter can be used to format the data or False otherwise.
     */
    public abstract boolean supportsFormatting();

    /**
     * Gets the mapping between the regular expression and the color to be used for drawing the text.
     *
     * @return The color to regular expression mappings.
     */
    public Map<Pattern, Color> getColorMappings() {
        return null;
    }

    /**
     * Apply the custom formatting on the data.
     *
     * @param value The data to format.
     * @return The formatted data.
     */
    public String format(String value) {
        return value;
    }

    @Override
    public int compareTo(TypeConverter o) {
        return this.getName().compareTo(o.getName());
    }

    @Override
    public boolean equals(Object obj) {
        return obj != null &&
            TypeConverter.class.isAssignableFrom(obj.getClass()) &&
            getName().equals(((TypeConverter) obj).getName());

    }

    @Override
    public int hashCode() {
        return getName().hashCode();
    }

    @Override
    public String toString() {
        return getName();
    }
    //endregion
}
